﻿// Copyright (c) 2007-2021 西安交通信息投资营运有限公司 版权所有
// 作者:吕艳阳

using System;
using System.Collections.Generic;
using XCI.Extensions;
using XCI.Helper;
using XCI.Windows;

namespace XCI.Core
{
    /// <summary>
    /// 行政区域控件管理
    /// </summary>
    public class AreaComboBoxEditManager
    {
        private object _dataObject;
        private ComboBoxEditx _provinceEdit;
        private ComboBoxEditx _cityEdit;
        private ComboBoxEditx _countyEdit;
        private ComboBoxEditx _townEdit;
        private readonly MutexStatus mutexStatus = new MutexStatus();

        /// <summary>
        /// 省份下拉控件
        /// </summary>
        public ComboBoxEditx ProvinceEdit
        {
            get => _provinceEdit;
            set
            {
                if (WinFormHelper.IsDesignMode()) return;
                _provinceEdit = value;

                //设置控件字段名称
                InitFieldMember(_provinceEdit);

                //加载省份数据
                BindControlDataSource(_provinceEdit, AreaDataManager.GetProvince());

                //绑定[省]事件
                BindControlSelectedValueChanged(_provinceEdit, v =>
                {
                    BindControlDataSource(_cityEdit, AreaDataManager.GetCity(v));
                    BindControlDataSource(_countyEdit, null);
                    BindControlDataSource(_townEdit, null);
                });
            }
        }

        /// <summary>
        /// 城市下拉控件
        /// </summary>
        public ComboBoxEditx CityEdit
        {
            get => _cityEdit;
            set
            {
                if (WinFormHelper.IsDesignMode()) return;
                _cityEdit = value;

                //设置控件字段名称
                InitFieldMember(_cityEdit);

                //绑定[市]事件
                BindControlSelectedValueChanged(_cityEdit, v =>
                {
                    BindControlDataSource(_countyEdit, AreaDataManager.GetCounty(v));
                    BindControlDataSource(_townEdit, null);
                });
            }
        }

        /// <summary>
        /// 区县下拉控件
        /// </summary>
        public ComboBoxEditx CountyEdit
        {
            get => _countyEdit;
            set
            {
                if (WinFormHelper.IsDesignMode()) return;
                _countyEdit = value;

                //设置控件字段名称
                InitFieldMember(_countyEdit);

                //绑定[区]事件
                BindControlSelectedValueChanged(_countyEdit, v =>
                {
                    BindControlDataSource(_townEdit, AreaDataManager.GetTown(v));
                });
            }
        }

        /// <summary>
        /// 街道下拉控件
        /// </summary>
        public ComboBoxEditx TownEdit
        {
            get => _townEdit;
            set
            {
                if (WinFormHelper.IsDesignMode()) return;
                _townEdit = value;

                //设置控件字段名称
                InitFieldMember(_townEdit);
            }
        }

        /// <summary>
        /// 省份标识字段
        /// </summary>
        public string ProvinceIdField { get; set; }

        /// <summary>
        /// 省份名称字段
        /// </summary>
        public string ProvinceNameField { get; set; }

        /// <summary>
        /// 城市标识字段
        /// </summary>
        public string CityIdField { get; set; }

        /// <summary>
        /// 城市名称字段
        /// </summary>
        public string CityNameField { get; set; }

        /// <summary>
        /// 区县标识字段
        /// </summary>
        public string CountyIdField { get; set; }

        /// <summary>
        /// 区县名称字段
        /// </summary>
        public string CountyNameField { get; set; }

        /// <summary>
        /// 街道标识字段
        /// </summary>
        public string TownIdField { get; set; }

        /// <summary>
        /// 街道名称字段
        /// </summary>
        public string TownNameField { get; set; }

        /// <summary>
        /// 读取或者设置控件值
        /// </summary>
        public AreaValue EditValue
        {
            get
            {
                return new AreaValue
                {
                    Province = GetControlValue(ProvinceEdit),//省
                    City = GetControlValue(CityEdit),//市
                    County = GetControlValue(CountyEdit), //区
                    Town = GetControlValue(TownEdit)//街道
                };
            }
            set
            {
                mutexStatus.Begin(() =>
                {
                    //省
                    SetControlValue(ProvinceEdit, value.Province);

                    //市
                    BindControlDataSourceAndSetControlValue(CityEdit, ProvinceEdit, value.City, AreaDataManager.GetCity);

                    //区
                    BindControlDataSourceAndSetControlValue(CountyEdit, CityEdit, value.County, AreaDataManager.GetCounty);

                    //街道
                    BindControlDataSourceAndSetControlValue(TownEdit, CountyEdit, value.Town, AreaDataManager.GetTown);
                });
            }
        }

        /// <summary>
        /// 取值和设值数据对象
        /// </summary>
        public object DataObject
        {
            get
            {
                if (_dataObject == null) return null;

                var val = EditValue;
                SetDataObjectValue(_dataObject, val.Province, ProvinceIdField, ProvinceNameField);
                SetDataObjectValue(_dataObject, val.City, CityIdField, CityNameField);
                SetDataObjectValue(_dataObject, val.County, CountyIdField, CountyNameField);
                SetDataObjectValue(_dataObject, val.Town, TownIdField, TownNameField);
                return _dataObject;
            }
            set
            {
                _dataObject = value;
                if (_dataObject == null) return;
                var df = AreaDataManager.GetDataObjectField(_dataObject);
                ProvinceIdField = df.ProvinceIdField;
                ProvinceNameField = df.ProvinceNameField;
                CityIdField = df.CityIdField;
                CityNameField = df.CityNameField;
                CountyIdField = df.CountyIdField;
                CountyNameField = df.CountyNameField;
                TownIdField = df.TownIdField;
                TownNameField = df.TownNameField;

                EditValue = new AreaValue
                {
                    Province = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, ProvinceIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, ProvinceNameField).ToStringOrEmpty()
                    },
                    City = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, CityIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, CityNameField).ToStringOrEmpty()
                    },
                    County = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, CountyIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, CountyNameField).ToStringOrEmpty()
                    },
                    Town = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, TownIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, TownNameField).ToStringOrEmpty()
                    }
                };
            }
        }

        private AreaModel GetControlValue(ComboBoxEditx edit)
        {
            var selected = edit?.SelectedItem;
            return selected as AreaModel;
        }

        private void SetControlValue(ComboBoxEditx edit, AreaModel model)
        {
            if (edit == null) return;
            if (!ValidAreaModel(model)) return;
            edit.SelectedValue = model.Id;
        }

        private void BindControlSelectedValueChanged(ComboBoxEditx edit, Action<string> action)
        {
            if (edit == null) return;
            edit.SelectedValueChanged += (s, b) =>
            {
                mutexStatus.End(() =>
                {
                    var selectedValue = ((ComboBoxEditx)s).SelectedValue.ToStringOrEmpty();
                    action(selectedValue);
                });
            };
        }

        private void BindControlDataSource(ComboBoxEditx edit, IList<AreaModel> dataSource)
        {
            if (edit == null) return;
            edit.DataSource = dataSource;
            edit.SelectedIndex = -1;
        }

        private bool ValidAreaModel(AreaModel model)
        {
            if (model == null || string.IsNullOrEmpty(model.Id)) return false;
            return true;
        }

        private void BindControlDataSourceAndSetControlValue(ComboBoxEditx current, ComboBoxEditx parent, AreaModel model, Func<string, IList<AreaModel>> dataSourceAction)
        {
            if (current == null || parent == null) return;
            if (!ValidAreaModel(model)) return;
            var selected = GetControlValue(parent);
            if (!ValidAreaModel(selected)) return;
            BindControlDataSource(current, dataSourceAction(selected.Id));
            SetControlValue(current, model);
        }

        private void InitFieldMember(ComboBoxEditx edit)
        {
            if (edit == null) return;

            edit.ValueMember = nameof(AreaModel.Id);
            edit.DisplayMember = nameof(AreaModel.Name);
        }

        private void SetDataObjectValue(object dataObject, AreaModel model, string idField, string nameField)
        {
            if (dataObject == null || model == null) return;

            ObjectHelper.SetObjectProperty(dataObject, idField, model.Id);
            ObjectHelper.SetObjectProperty(dataObject, nameField, model.Name);
        }


    }
}